Skip to content

Add Support nested act claim with azp and multi-audience in token request#3028

Open
Bin4yi wants to merge 23 commits intowso2-extensions:masterfrom
Bin4yi:act-sub-azp
Open

Add Support nested act claim with azp and multi-audience in token request#3028
Bin4yi wants to merge 23 commits intowso2-extensions:masterfrom
Bin4yi:act-sub-azp

Conversation

@Bin4yi
Copy link
Copy Markdown

@Bin4yi Bin4yi commented Feb 4, 2026

Proposed changes in this pull request

OAuthConstants.java

  • Introduced constants for delegation-related property keys: ACTOR_AZP, IS_DELEGATION_REQUEST, ACTOR_SUBJECT, EXISTING_ACT_CLAIM, and DELEGATING_ACTOR

OAuthAuthzReqMessageContext.java

  • Added audiences field with getter and setter to support explicit audience specification in authorization requests

AbstractAuthorizationGrantHandler.java

  • In updateMessageContextToCreateNewToken(), default audiences are only set when not already specified by the grant handler (prevents overwriting explicitly requested audiences)
  • In getAccessTokenExtendedAttributes(), persists DELEGATING_ACTOR as an extended token attribute when the request is a delegation request — enables downstream propagation (e.g. refresh token flow, session-bound revocation)

OAuthTokenReqMessageContext.java

  • Added isDelegationRequest boolean field with isDelegationRequest() getter and setDelegationRequest() setter to distinguish delegation flows from impersonation flows

AuthorizationCodeGrantHandler.java

  • Extracts azp and act claims from the actor token during token exchange
  • Sets delegation context properties (IS_DELEGATION_REQUEST, ACTOR_SUBJECT, ACTOR_AZP, EXISTING_ACT_CLAIM) on the token request context to drive act claim construction in the JWT issuer
  • Existing act claim from the actor token is preserved for chained delegation nesting

JWTTokenIssuer.java

  • Added explicit audience override in both buildJWTToken() overloads — when audiences are already set on the context, they take precedence over the OIDC default audience
  • Added act claim construction for delegation requests:
    • Builds act claim with sub (actor subject) and optionally azp (actor authorized party)
    • Supports chained/nested delegation — when an existing act claim is present in the actor token, it is nested inside the new act claim
    • Regular self-delegation (no existing act claim) does not add any act claim
    • Impersonation continues to use may_act in the subject token — unaffected

AccessTokenIssuer.java

  • Added diagnostic logging for delegation flows, recording delegating_actor in the audit log alongside the existing impersonation logging

RefreshGrantHandler.java

  • Renamed propagateImpersonationInfo() to propagateActorInfo() to handle both impersonation and delegation flows
  • On refresh token grant, reads DELEGATING_ACTOR from the stored extended attributes and propagates it back into the token request context so that refreshed tokens carry the correct act claim

TokenBindingExpiryEventHandler.java

  • Added validateDelegatingActorInitiatedRevocation() — session-bound token revocation is now also triggered when the delegating actor terminates their session, mirroring the existing behaviour for impersonating actors

DelegatedAccessTokenClaimProvider.java (new)

  • New JWTAccessTokenClaimProvider implementation for the delegation flow
  • Returns an act claim containing the sub of the delegating actor when isDelegationRequest is true and DELEGATING_ACTOR is set

Sample delegated access token (chained delegation):

{
  "sub": "11111111-2222-3333-4444-555555555555",
  "aut": "APPLICATION_USER",
  "iss": "https://example.com/oauth2/token",
  "client_id": "client_ABC123XYZ",
  "aud": [
    "client_ABC123XYZ",
    "aud_service_READ_001",
    "aud_service_WRITE_002"
  ],
  "nbf": 1770000000,
  "act": {
    "sub": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "act": {
      "sub": "ffffffff-1111-2222-3333-444444444444",
      "azp": "client_ABC123XYZ"
    },
    "azp": "client_ABC123ABC"
  },
  "azp": "client_ABC123ABC",
  "org_id": "org_00112233",
  "scope": "booking:read",
  "exp": 1770003600,
  "org_name": "ExampleOrg",
  "iat": 1770000000,
  "jti": "jwtid_9f8e7d6c5b4a",
  "org_handle": "example.org"
}

Developer Checklist (Mandatory)

  • Complete the Developer Checklist in the related product-is issue to track any behavioral change or migration impact.

Checklist (for reviewing)

General

  • Is this PR explained thoroughly? All code changes must be accounted for in the PR description.
  • Is the PR labeled correctly?

Functionality

  • Are all requirements met? Compare implemented functionality with the requirements specification.
  • Does the UI work as expected? There should be no Javascript errors in the console; all resources should load. There should be no unexpected errors. Deliberately try to break the feature to find out if there are corner cases that are not handled.

Code

  • Do you fully understand the introduced changes to the code? If not ask for clarification, it might uncover ways to solve a problem in a more elegant and efficient way.
  • Does the PR introduce any inefficient database requests? Use the debug server to check for duplicate requests.
  • Are all necessary strings marked for translation? All strings that are exposed to users via the UI must be marked for translation.

Tests

  • Are there sufficient test cases? Ensure that all components are tested individually; models, forms, and serializers should be tested in isolation even if a test for a view covers these components.
  • If this is a bug fix, are tests for the issue in place? There must be a test case for the bug to ensure the issue won’t regress. Make sure that the tests break without the new code to fix the issue.
  • If this is a new feature or a significant change to an existing feature? has the manual testing spreadsheet been updated with instructions for manual testing?

Security

  • Confirm this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.
  • Are all UI and API inputs run through forms or serializers?
  • Are all external inputs validated and sanitized appropriately?
  • Does all branching logic have a default case?
  • Does this solution handle outliers and edge cases gracefully?
  • Are all external communications secured and restricted to SSL?

Documentation

  • Are changes to the UI documented in the platform docs? If this PR introduces new platform site functionality or changes existing ones, the changes should be documented.
  • Are changes to the API documented in the API docs? If this PR introduces new API functionality or changes existing ones, the changes must be documented.
  • Are reusable components documented? If this PR introduces components that are relevant to other developers (for instance a mixin for a view or a generic form) they should be documented in the Wiki.

Summary by CodeRabbit

  • New Features
    • Actor-token delegation across OAuth flows: issued tokens include an act claim (supports nested/chained delegation) and azp metadata when available; delegating-actor info is recorded for revocation and diagnostic messages. Authorization requests can carry explicit audiences that are preserved into issued tokens.
  • Tests
    • Added unit tests covering audience preservation, delegation act-claim scenarios, claim provider behavior, and delegation propagation.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds delegation support across OAuth flows: new constants, delegation flags/properties on authz/token contexts, audience passthrough, construction of "act" claims (including nested/chained delegation), propagation/storage of a delegating actor in token attributes, token-revocation updates, a new DelegatedAccessTokenClaimProvider, and related unit tests.

Changes

Cohort / File(s) Summary
OAuth Constants
components/org.wso2.carbon.identity.oauth.common/src/main/java/org/wso2/carbon/identity/oauth/common/OAuthConstants.java
Added delegation constants: ACTOR_AZP, IS_DELEGATION_REQUEST, ACTOR_SUBJECT, EXISTING_ACT_CLAIM, and DELEGATING_ACTOR.
JWT issuance & authz context
components/org.wso2.carbon.identity.oauth/src/main/java/.../JWTTokenIssuer.java, components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java
JWTTokenIssuer honors request.getAudiences() and builds delegated act claim (uses ACTOR_SUBJECT, optional ACTOR_AZP, nests EXISTING_ACT_CLAIM if Map). Added audiences field + getter/setter to authz request context.
Agent & Delegation claim providers
components/org.wso2.carbon.identity.oauth/src/main/java/.../AgentAccessTokenClaimProvider.java, components/org.wso2.carbon.identity.oauth/src/main/java/.../DelegatedAccessTokenClaimProvider.java
Agent provider now includes azp in agent act (from context or fallback to clientId). Added DelegatedAccessTokenClaimProvider to emit act claim when delegation is active and DELEGATING_ACTOR present.
Grant handlers & propagation
components/org.wso2.carbon.identity.oauth/src/main/java/.../AuthorizationCodeGrantHandler.java, .../RefreshGrantHandler.java, .../AbstractAuthorizationGrantHandler.java
AuthorizationCodeGrantHandler extracts actor azp and existing act claim and sets delegation properties on token context. RefreshGrantHandler replaces/renames helper to propagateActorInfo to handle impersonation/delegation. AbstractAuthorizationGrantHandler injects DELEGATING_ACTOR into extended attributes and preserves existing audiences when present.
Token request context
components/org.wso2.carbon.identity.oauth/src/main/java/.../OAuthTokenReqMessageContext.java
Added isDelegationRequest flag with getter/setter to token request context.
Access token issuance diagnostics
components/org.wso2.carbon.identity.oauth/src/main/java/.../AccessTokenIssuer.java
Diagnostics now log delegating actor when isDelegationRequest() is true and DELEGATING_ACTOR present; message adjusted for delegated issuance.
Token revocation handler
components/org.wso2.carbon.identity.oauth/src/main/java/.../TokenBindingExpiryEventHandler.java
Added detection of delegating-actor–initiated revocation (checks DELEGATING_ACTOR extended attribute) and unified actor-initiated revocation logic to include delegating actor.
Tests & TestNG config
components/org.wso2.carbon.identity.oauth/src/test/java/.../JWTTokenIssuerTest.java, .../DelegatedAccessTokenClaimProviderTest.java, .../AbstractAuthorizationGrantHandlerTest.java, .../RefreshGrantHandlerTest.java, components/org.wso2.carbon.identity.oauth/src/test/resources/testng.xml
Added tests for audience passthrough, delegation act claim construction (including chained cases), DelegatedAccessTokenClaimProvider behavior, propagation of delegating actor into extended attributes, and updated TestNG suite entries.
New public class
components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/DelegatedAccessTokenClaimProvider.java
New claim provider added to emit act claim for delegating-actor scenarios.

Sequence Diagram

sequenceDiagram
    participant Client
    participant AuthzHandler as AuthorizationCodeGrantHandler
    participant TokenCtx as OAuthTokenReqMessageContext
    participant GrantHandler as Refresh/GrantHandler
    participant JWTIssuer as JWTTokenIssuer
    participant ClaimProvider as Delegated/AgentClaimProvider

    Client->>AuthzHandler: submit authorization / actor token
    AuthzHandler->>AuthzHandler: extract actor sub, azp, existing act
    AuthzHandler->>TokenCtx: set IS_DELEGATION_REQUEST, ACTOR_SUBJECT, ACTOR_AZP, EXISTING_ACT_CLAIM
    Client->>GrantHandler: token request
    GrantHandler->>GrantHandler: propagate actor info -> set DELEGATING_ACTOR attr
    GrantHandler->>JWTIssuer: createJWTClaimSet(tokenReqCtx)
    rect rgba(100,150,200,0.5)
      JWTIssuer->>JWTIssuer: if isDelegationRequest build "act" claim (sub, azp, nest existing act)
      JWTIssuer->>JWTIssuer: set audience from request.getAudiences() if present
    end
    JWTIssuer->>ClaimProvider: getAdditionalClaims(tokenCtx)
    ClaimProvider->>ClaimProvider: provide act claim for access token if delegation present
    ClaimProvider-->>Client: return enriched token / JWT
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • piraveena
  • shashimalcse
  • jenkins-is-staging

Poem

🐰 I hopped into code with a tiny cheer,
Act and azp now whisper clear,
Delegations nest in a careful stack,
Audiences kept; actors leave a track,
Hop—tokens carry friends back home!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely summarizes the main changes: adding support for nested act claims with azp (authorized party) and multi-audience handling in token requests, which aligns with the comprehensive delegation and audience-handling implementation across multiple OAuth components.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering Purpose (delegation support with nested act claims), Goals (handling azp, nested delegation, multi-audience), Approach (detailed changes per file), a sample delegated token with chained delegation, and addresses security and testing aspects.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/AgentAccessTokenClaimProvider.java`:
- Around line 14-15: The provider overwrites any existing nested delegation
chain by replacing the act claim with a flat {sub, azp} when
AgentAccessTokenClaimProvider applies provider claims; update
AgentAccessTokenClaimProvider (the branch handling ACTOR_AZP/ACTOR_* in
buildJWTToken flow) to merge with an existing act claim instead of replacing it:
detect EXISTING_ACT_CLAIM built by JWTTokenIssuer.createJWTClaimSet(..),
preserve nested act entries and append/merge the new actor (azp/sub) into the
existing structure rather than clobbering it, and add a regression test that
issues an actor token already containing an act claim and asserts the nested
delegation chain is retained; apply the same fix to the other similar branch
(lines referenced as 42-60) to ensure consistency.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b890f506-69a7-4411-9044-8c5f29bb6d14

📥 Commits

Reviewing files that changed from the base of the PR and between 158822f and 1c4b0e8.

📒 Files selected for processing (4)
  • components/org.wso2.carbon.identity.oauth.common/src/main/java/org/wso2/carbon/identity/oauth/common/OAuthConstants.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/AgentAccessTokenClaimProvider.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java

Comment on lines +14 to +15
import static org.wso2.carbon.identity.oauth.common.OAuthConstants.ACTOR_AZP;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

This branch overwrites the nested delegation chain.

JWTTokenIssuer.createJWTClaimSet(..) already builds the delegation act claim from ACTOR_* plus EXISTING_ACT_CLAIM. Because provider claims are applied afterward in buildJWTToken(..), this branch replaces it with a flat {sub, azp} and drops any incoming nested act. Please add a regression test with an actor token that already contains act.

🛠️ Minimal fix
 import static org.wso2.carbon.identity.oauth.common.OAuthConstants.ACTOR_AZP;
+import static org.wso2.carbon.identity.oauth.common.OAuthConstants.IS_DELEGATION_REQUEST;
@@
-        } else if (GrantType.AUTHORIZATION_CODE.toString().equals(context.getOauth2AccessTokenReqDTO().getGrantType())
-            && context.getRequestedActor() != null) {
+        } else if (GrantType.AUTHORIZATION_CODE.toString().equals(context.getOauth2AccessTokenReqDTO().getGrantType())
+                && context.getRequestedActor() != null
+                && !Boolean.TRUE.equals(context.getProperty(IS_DELEGATION_REQUEST))) {

Also applies to: 42-60

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/AgentAccessTokenClaimProvider.java`
around lines 14 - 15, The provider overwrites any existing nested delegation
chain by replacing the act claim with a flat {sub, azp} when
AgentAccessTokenClaimProvider applies provider claims; update
AgentAccessTokenClaimProvider (the branch handling ACTOR_AZP/ACTOR_* in
buildJWTToken flow) to merge with an existing act claim instead of replacing it:
detect EXISTING_ACT_CLAIM built by JWTTokenIssuer.createJWTClaimSet(..),
preserve nested act entries and append/merge the new actor (azp/sub) into the
existing structure rather than clobbering it, and add a regression test that
issues an actor token already containing an act claim and asserts the nested
delegation chain is retained; apply the same fix to the other similar branch
(lines referenced as 42-60) to ensure consistency.

Co-authored-by: Pavindu Lakshan <pavindulakshan@gmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/DelegatedAccessTokenClaimProvider.java`:
- Around line 35-41: DelegatedAccessTokenClaimProvider is defined but not
registered and will conflict with JWTTokenIssuer's existing delegation handling
by emitting a flat act claim; either remove this provider, register and
integrate it properly, or disable its act emission so only JWTTokenIssuer builds
nested act structures. Specifically, either delete or unregister
DelegatedAccessTokenClaimProvider (to match how
ImpersonatedAccessTokenClaimProvider and AgentAccessTokenClaimProvider are
registered in OAuth2ServiceComponent), or modify
DelegatedAccessTokenClaimProvider so it consults EXISTING_ACT_CLAIM and defers
to JWTTokenIssuer's logic (lines handling DELEGATING_ACT and ACT) rather than
returning a standalone act:{sub:...} map; ensure only JWTTokenIssuer constructs
the nested act/azp chain to avoid duplicate act claim emission.

In
`@components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/OAuthTokenReqMessageContext.java`:
- Around line 223-226: Setter setDelegationRequest currently assigns the value
to isImpersonationRequest instead of the delegation flag; change the method
(setDelegationRequest) to set the isDelegationRequest field to the passed
delegationRequest value (do not flip isImpersonationRequest), so downstream
checks like isDelegationRequest() and isImpersonationRequest() behave correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a1d3f1d0-a22d-444e-93d2-a4aa85b56e75

📥 Commits

Reviewing files that changed from the base of the PR and between 1c4b0e8 and 7700b80.

📒 Files selected for processing (9)
  • components/org.wso2.carbon.identity.oauth.common/src/main/java/org/wso2/carbon/identity/oauth/common/OAuthConstants.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/OAuthTokenReqMessageContext.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/bindings/handlers/TokenBindingExpiryEventHandler.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/DelegatedAccessTokenClaimProvider.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java
  • components/org.wso2.carbon.identity.oauth.common/src/main/java/org/wso2/carbon/identity/oauth/common/OAuthConstants.java

Comment on lines +35 to +41
if (context.isDelegationRequest()
&& context.getProperty(DELEGATING_ACTOR) != null
&& StringUtils.isNotBlank(context.getProperty(DELEGATING_ACTOR).toString())) {

Map<String, Object> actorMap = new HashMap<>();
actorMap.put(ACT, Collections.singletonMap(SUB, context.getProperty(DELEGATING_ACTOR).toString()));
return actorMap;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show where JWT access-token claim providers are discovered and used.
rg -n -C3 --type=java 'JWTAccessTokenClaimProvider|DelegatedAccessTokenClaimProvider|getAdditionalClaims\('

printf '\n--- JWTTokenIssuer.java ---\n'
fd 'JWTTokenIssuer.java' -x sed -n '1,320p' {}

printf '\n--- act/azp handling ---\n'
rg -n -C3 --type=java 'DELEGATING_ACTOR|ACTOR_AZP|EXISTING_ACT|\bact\b|\bazp\b'

Repository: wso2-extensions/identity-inbound-auth-oauth

Length of output: 50400


🏁 Script executed:

#!/bin/bash

# Find and show JWTTokenIssuer.java - look for claim merging logic
fd 'JWTTokenIssuer.java' --type f ! -path '*/test/*' -x cat {} | head -400

# Look for setAdditionalClaimSet and related merge logic
echo -e '\n--- Claim merge method ---'
rg -n 'setAdditionalClaimSet|mergeAdditional|getAdditionalClaims' --type=java -A5 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java

# Check how providers are registered and called
echo -e '\n--- Provider registration and call sites ---'
rg -n 'getJWTAccessTokenClaimProvider|addJWTAccessTokenClaimProvider' --type=java components/org.wso2.carbon.identity.oauth/src/main/java/ -B2 -A2

# Look for act claim specific handling
echo -e '\n--- ACT claim handling in JWTTokenIssuer ---'
rg -n '"act"|ACT' --type=java components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java -B3 -A3

Repository: wso2-extensions/identity-inbound-auth-oauth

Length of output: 11453


🏁 Script executed:

#!/bin/bash

# Search for where DelegatedAccessTokenClaimProvider is instantiated/registered in production
echo "=== DelegatedAccessTokenClaimProvider registration ==="
rg -n 'new DelegatedAccessTokenClaimProvider|DelegatedAccessTokenClaimProvider' \
  --type=java components/org.wso2.carbon.identity.oauth/src/main/java/ -B2 -A2

# Check component activator/descriptor files
echo -e '\n=== Component descriptors ==='
find components/org.wso2.carbon.identity.oauth/src/main -name '*.xml' -o -name 'component.properties' | head -10

# Search for META-INF ServiceLoader config
echo -e '\n=== ServiceLoader configs ==='
find components/org.wso2.carbon.identity.oauth -path '*/META-INF/services/*' -type f 2>/dev/null | xargs cat 2>/dev/null | grep -i 'delegated\|claim'

# Show how other providers (ImpersonatedAccessTokenClaimProvider, AgentAccessTokenClaimProvider) are registered
echo -e '\n=== ImpersonatedAccessTokenClaimProvider registration ==='
rg -n 'ImpersonatedAccessTokenClaimProvider' --type=java components/org.wso2.carbon.identity.oauth/src/main/java/ -B1 -A1 | head -20

Repository: wso2-extensions/identity-inbound-auth-oauth

Length of output: 3337


🏁 Script executed:

#!/bin/bash

# Check OAuth2ServiceComponent for DelegatedAccessTokenClaimProvider registration
echo "=== OAuth2ServiceComponent for DelegatedAccessTokenClaimProvider ==="
rg -n 'DelegatedAccessTokenClaimProvider' components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java -B5 -A5

# Show the full registration section
echo -e '\n=== Full provider registration section ==='
sed -n '285,295p' components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java

# Also check imports in OAuth2ServiceComponent
echo -e '\n=== Imports around claim providers ==='
rg -n 'import.*AccessTokenClaimProvider' components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java

Repository: wso2-extensions/identity-inbound-auth-oauth

Length of output: 1333


🏁 Script executed:

#!/bin/bash

# Search for tests using DelegatedAccessTokenClaimProvider
echo "=== Test files for DelegatedAccessTokenClaimProvider ==="
find components/org.wso2.carbon.identity.oauth -name '*DelegatedAccessTokenClaimProvider*' -type f

# Check if there's a test and what it does
echo -e '\n=== DelegatedAccessTokenClaimProvider Test ==='
find components/org.wso2.carbon.identity.oauth -name '*DelegatedAccessTokenClaimProvider*Test*' -type f -exec cat {} \;

# Look for any TODO/FIXME comments near delegation or act claims
echo -e '\n=== TODO/FIXME around delegation ==='
rg -n 'TODO|FIXME' --type=java components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/

# Look for any comment explaining delegation flow
echo -e '\n=== Comments about delegation in DelegatedAccessTokenClaimProvider ==='
sed -n '1,60p' components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/DelegatedAccessTokenClaimProvider.java

Repository: wso2-extensions/identity-inbound-auth-oauth

Length of output: 2086


DelegatedAccessTokenClaimProvider is not registered and conflicts with JWTTokenIssuer's delegation handling.

This provider is defined but never instantiated (unlike ImpersonatedAccessTokenClaimProvider and AgentAccessTokenClaimProvider, which are registered in OAuth2ServiceComponent lines 288-291). When examined, JWTTokenIssuer already provides dedicated delegation act claim handling (lines 741–787) that correctly builds nested act structures with azp and chains via EXISTING_ACT_CLAIM.

If this provider is intended to be wired, it will emit a flat act: {sub: ...} structure that conflicts with JWTTokenIssuer's superior nested handling. Either remove the provider as unnecessary, register it with proper integration into JWTTokenIssuer's delegation logic, or clarify its intended activation point. Do not emit act claims from multiple independent paths.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/DelegatedAccessTokenClaimProvider.java`
around lines 35 - 41, DelegatedAccessTokenClaimProvider is defined but not
registered and will conflict with JWTTokenIssuer's existing delegation handling
by emitting a flat act claim; either remove this provider, register and
integrate it properly, or disable its act emission so only JWTTokenIssuer builds
nested act structures. Specifically, either delete or unregister
DelegatedAccessTokenClaimProvider (to match how
ImpersonatedAccessTokenClaimProvider and AgentAccessTokenClaimProvider are
registered in OAuth2ServiceComponent), or modify
DelegatedAccessTokenClaimProvider so it consults EXISTING_ACT_CLAIM and defers
to JWTTokenIssuer's logic (lines handling DELEGATING_ACT and ACT) rather than
returning a standalone act:{sub:...} map; ensure only JWTTokenIssuer constructs
the nested act/azp chain to avoid duplicate act claim emission.

@Bin4yi Bin4yi changed the title Supports nested act sub claim with azp claim inside it Add Support nested act claim with azp and multi-audience in token request Mar 19, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuerTest.java (1)

657-660: Strengthen chained-delegation assertion with nested claim content checks.

At Line 658, the test currently checks only nested act presence. Assert nested sub/azp values as well to catch mapping regressions.

Suggested test hardening
                 if (expectNestedAct) {
                     assertNotNull(actClaim.get("act"), "Nested act claim should be present for chained delegation");
+                    Map<String, Object> nestedAct = (Map<String, Object>) actClaim.get("act");
+                    assertEquals(nestedAct.get("sub"), "previous-actor",
+                            "Nested act.sub should preserve prior actor subject");
+                    assertEquals(nestedAct.get("azp"), "previous-azp",
+                            "Nested act.azp should preserve prior actor azp");
                 } else {
                     assertNull(actClaim.get("act"), "No nested act claim expected");
                 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuerTest.java`
around lines 657 - 660, The chained-delegation test should not only assert
presence of the nested "act" claim but also verify its contents: when
expectNestedAct is true, obtain the nested map (Object nestedAct =
actClaim.get("act")) and assert its "sub" and "azp" entries equal the expected
delegated subject and client id used earlier in the test (e.g., the variables
representing the delegated subject and authorized party), likewise keep the
existing assertNull branch for when expectNestedAct is false; update
JWTTokenIssuerTest to add these assertEquals checks against the expected values
so mapping regressions are detected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuerTest.java`:
- Around line 657-660: The chained-delegation test should not only assert
presence of the nested "act" claim but also verify its contents: when
expectNestedAct is true, obtain the nested map (Object nestedAct =
actClaim.get("act")) and assert its "sub" and "azp" entries equal the expected
delegated subject and client id used earlier in the test (e.g., the variables
representing the delegated subject and authorized party), likewise keep the
existing assertNull branch for when expectNestedAct is false; update
JWTTokenIssuerTest to add these assertEquals checks against the expected values
so mapping regressions are detected.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e1434530-05ac-4760-81e2-e6e82b3b2797

📥 Commits

Reviewing files that changed from the base of the PR and between 45d0f85 and 697e0a3.

📒 Files selected for processing (5)
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/OAuthTokenReqMessageContext.java
  • components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuerTest.java
  • components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/DelegatedAccessTokenClaimProviderTest.java
  • components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandlerTest.java
  • components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandlerTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/OAuthTokenReqMessageContext.java

Bin4yi added 6 commits March 23, 2026 10:24
# Conflicts:
#	components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java
#	components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/claims/AgentAccessTokenClaimProvider.java
#	components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/ActorTokenValidator.java
#	components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 44.82759% with 64 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.25%. Comparing base (02662c8) to head (edd02f8).
⚠️ Report is 88 commits behind head on master.

Files with missing lines Patch % Lines
.../handlers/grant/AuthorizationCodeGrantHandler.java 0.00% 14 Missing ⚠️
...dings/handlers/TokenBindingExpiryEventHandler.java 0.00% 12 Missing ⚠️
...2/carbon/identity/oauth2/token/JWTTokenIssuer.java 60.71% 6 Missing and 5 partials ⚠️
...uth2/token/handlers/grant/RefreshGrantHandler.java 50.00% 6 Missing and 4 partials ⚠️
...arbon/identity/oauth2/token/AccessTokenIssuer.java 0.00% 6 Missing ⚠️
...handlers/claims/AgentAccessTokenClaimProvider.java 55.55% 2 Missing and 2 partials ⚠️
...uth2/token/handlers/grant/ActorTokenValidator.java 75.00% 2 Missing and 2 partials ⚠️
...tity/oauth2/authz/OAuthAuthzReqMessageContext.java 33.33% 2 Missing ⚠️
...dlers/grant/AbstractAuthorizationGrantHandler.java 80.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3028      +/-   ##
============================================
- Coverage     59.70%   57.25%   -2.46%     
- Complexity    10162    10731     +569     
============================================
  Files           708      709       +1     
  Lines         55447    61504    +6057     
  Branches      13134    14893    +1759     
============================================
+ Hits          33104    35213    +2109     
- Misses        17993    21525    +3532     
- Partials       4350     4766     +416     
Flag Coverage Δ
unit 42.74% <44.82%> (+0.08%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants